/*
 * Written by Patrick Black, Dustin Striplin, Samba, Phat le
 */
package FileParser;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.TreeSet;

import javax.swing.JOptionPane;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerFactoryConfigurationError;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import Model.Conference;
import Model.Manuscript;
import Model.Review;
import Model.Roles;


public class FileParser {
	public static final String CONFERENCE = "Conference"; // the way the xml tag
												// is spelled
	public static final String MANUSCRIPT = "Manuscript"; // the way the xml tag
															// is spelled
	public static final String NAME = "name"; // the way the xml attribute is
												// spelled.
	public static final String DATE = "date"; // ditto
	public static final String VENUE = "venue"; // ...
	public static final String DEADLINE = "deadline";
	public static final String LINK = "link";
	public static final String RECOMMENDATION = "rec";
	public static final String APPROVAL = "approval";
	private static final int MAX_REVIEWERS = 3;
	private static final int MAX_PAPERS = 4;

	private Document doc;
	
	/**
	 * Create a file parser & parse the conference
	 * @author Dustin Striplin
	 */
	public FileParser() {
		// create a file parser, and store the xml document as a dom in memory
		InputStream stream = FileParser.class
				.getResourceAsStream("/xmlfiles/conferences.xml");
		try {
			DocumentBuilderFactory dbFactory = DocumentBuilderFactory
					.newInstance();
			DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
			doc = dBuilder.parse(stream); // create dom
			stream.close(); // stream no longer needed, so close it.
			doc.getDocumentElement().normalize();
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	/**
	 * Returns a list of manuscripts that the user is associated with
	 * 
	 * @author Dustin Striplin 
	 * @param role The role of the user
	 * @param name The name of the user
	 * @param conference The conference in question
	 * @return An arraylist containing the manuscripts for this user
	 */
	@SuppressWarnings("rawtypes")
	public ArrayList<Manuscript> getManuscripts(final String role,
			final String name, final String conference) {
		ArrayList<Manuscript> manuscriptList = new ArrayList<Manuscript>();

		NodeList nList = doc.getElementsByTagName(CONFERENCE); // generate a
																// node list of
																// conferences
		Element cEle = getElementFromList(nList, conference); // find the
																// correct
																// conference.

		// get a list of each instance of this role from the conference
		if (cEle != null) {
			nList = cEle.getElementsByTagName(role); // a node list containing
														// only elements of type
														// role
			manuscriptList = generateManuscripts(cEle, nList, conference, name); // get
																					// a
																					// list
																					// of
																					// manuscripts
																					// for
																					// this
																					// user,
																					// in
			// this conference.
		}
		return manuscriptList;
	}

	// TODO check the users role, and only generate the manuscripts for that
	// role.
	/**
	 * Generates a list of manuscripts this user is associated with
	 * 
	 * @param nList
	 *            the list of all instances the role that this user is, may
	 *            include other users, of the same role.
	 * @param conference
	 *            The title of the conference.
	 * @param name
	 *            the name of the user.
	 * @return The list of manuscripts.
	 */
	private ArrayList<Manuscript> generateManuscripts(final Element confEle,
			final NodeList nList, final String conference, final String name) {
		ArrayList<Manuscript> mList = new ArrayList<Manuscript>();
		Element ele; // the current element we are checking
		Element parent; // the parent of ele, this can be either Conference, or
						// Manuscript.
		Conference conf = generateConference(confEle); // create a conference
														// object to store in
														// all
														// manuscripts that are
														// created in this
														// method
														// since all manuscripts
														// are from the same
														// conference.
		if (conf == null)
			return null; // TODO should send an error, but... I might do that
							// later
		// loop through node list
		// check if this node is associated with the user
		// if it is then create a manuscript
		// set all of the fields
		// then add the manuscript to the ArrayList.
		for (int i = 0; i < nList.getLength(); i++) {
			ele = (Element) nList.item(i);
			if (ele.getAttribute(NAME).equals(name)) { // check if the element
														// is associated with
														// this user
				parent = (Element) ele.getParentNode(); // look at parent node,
				if (parent.getNodeName().equals(MANUSCRIPT)) { // check if the
																// Element is a
																// descendant of
																// Manuscript

					String author, title, pc, subpc, paperLink; // create
																// variables for
																// input to the
																// manuscript
					int recommendation, approval;
					ArrayList<Review> reviews = null;

					title = parent.getAttribute(NAME); // get attributes from
														// Manuscript tag
					paperLink = parent.getAttribute(LINK);
					recommendation = Integer.parseInt(parent
							.getAttribute(RECOMMENDATION));
					approval = Integer.parseInt(parent.getAttribute(APPROVAL));

					pc = getName(parent, Roles.PC.toString()); // get pc name
					subpc = getName(parent, Roles.SUBPC.toString()); // get
																		// subpc
																		// name
					author = getName(parent, Roles.AUTHOR.toString()); // get
																		// author
																		// name

					reviews = getReviews(parent); // get a list of review
													// objects containing
													// the reviewer name, and a
													// link to the review.

					mList.add(new Manuscript(author, title, paperLink, pc,
							subpc, recommendation, approval, conf, reviews));
				}
			}
		}
		return mList;
	}

	/**
	 * Creates an ArrayList of reviewers for the manuscript
	 * 
	 * @param parent
	 *            The manuscript
	 * @return an ArrayList containing a Review object for each review/reviewer.
	 */
	private ArrayList<Review> getReviews(final Element parent) {
		ArrayList<Review> rList = new ArrayList<Review>();
		NodeList list = parent.getElementsByTagName(Roles.REVIEWER.toString()); // get
																				// a
																				// NodeList
																				// of
																				// Reviewer
																				// Nodes

		for (int i = 0; i < list.getLength(); i++) { // generate a Review object
														// for each
														// review/reviewer
			Element reviewer = (Element) list.item(i);
			rList.add(new Review(reviewer.getAttribute(NAME), reviewer
					.getAttribute(LINK))); // add to ArrayList
		}

		return rList;
	}

	/**
	 * Assign Paper
	 * @throws TransformerException 
	 */
	public void assignPaper(final String a_reviewer, final Manuscript a_manuscript) {
		InputStream stream = FileParser.class.getResourceAsStream("/xmlfiles/conferences.xml");
		try {
			DocumentBuilderFactory dbFactory = DocumentBuilderFactory
					.newInstance();
			DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
			doc = dBuilder.parse(stream); // create dom
			stream.close(); // stream no longer needed, so close it.
			doc.getDocumentElement().normalize();
			NodeList manuList = doc.getElementsByTagName(MANUSCRIPT);
			for(int i = 0; i < manuList.getLength(); i++) {
				Element manu = (Element) manuList.item(i);
				System.out.println(manu.getAttribute(NAME) + " vs " + a_manuscript.getTitle());
				if(manu.getAttribute(NAME).equalsIgnoreCase(a_manuscript.getTitle()) && 
						manu.getElementsByTagName("Reviewer").getLength() < MAX_REVIEWERS){
					Element reviewer = doc.createElement("Reviewer");

					Attr paperlinkAttr = doc.createAttribute("paper_link");
					paperlinkAttr.setValue(a_manuscript.getLink());
					reviewer.setAttributeNode(paperlinkAttr);

					Attr linkAttr = doc.createAttribute("link");
					linkAttr.setValue("");
					reviewer.setAttributeNode(linkAttr);
								
					Attr reviewerAttr = doc.createAttribute("name");
					reviewerAttr.setValue(a_reviewer);
					reviewer.setAttributeNode(reviewerAttr);			
					
					
					manu.appendChild(reviewer);
					System.out.println("It went here");
					break;
				}
			}
			File aFile = new File("src/xmlfiles/conferences.xml");
			// save the result
			TransformerFactory transformerFactory = TransformerFactory.newInstance();
			Transformer transformer = transformerFactory.newTransformer();
			transformer.setOutputProperty(OutputKeys.INDENT, "yes");
			transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "3");
			transformer.transform(new DOMSource(doc), new StreamResult(aFile));
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * Assign Paper
	 * @throws TransformerException 
	 */
	public void designateSubProgramChair(final String a_spc, final Manuscript a_manuscript) {
		InputStream stream = FileParser.class.getResourceAsStream("/xmlfiles/conferences.xml");
		try {
			DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
			DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
			doc = dBuilder.parse(stream); // create dom
			stream.close(); // stream no longer needed, so close it.
			doc.getDocumentElement().normalize();
			int numberOfSPC = 0;
			NodeList spcList = doc.getElementsByTagName("SubPC");
			for(int j = 0; j < spcList.getLength(); j++){
				Element spcEle = (Element) spcList.item(j);
				if(spcEle.getAttribute(NAME).equalsIgnoreCase(a_spc)){
					numberOfSPC++;
				}
			}
			System.out.println("Number of SPC:" + numberOfSPC);
			NodeList manuList = doc.getElementsByTagName(MANUSCRIPT);
			for(int i = 0; i < manuList.getLength(); i++) {
				Element manu = (Element) manuList.item(i);
				System.out.println(manu.getAttribute(NAME) + " vs " + a_manuscript.getTitle());
				if(manu.getAttribute(NAME).equalsIgnoreCase(a_manuscript.getTitle()) && 
						manu.getElementsByTagName("SubPC").getLength() != 1 &&
						numberOfSPC != MAX_PAPERS){
					Element spc = doc.createElement("SubPC");
					Attr spcAttr = doc.createAttribute("name");
					spcAttr.setValue(a_spc);
					spc.setAttributeNode(spcAttr);			
					manu.appendChild(spc);
					File aFile = new File("src/xmlfiles/conferences.xml");
					TransformerFactory transformerFactory = TransformerFactory.newInstance();
					Transformer transformer = transformerFactory.newTransformer();
					transformer.setOutputProperty(OutputKeys.INDENT, "yes");
					transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "3");
					transformer.transform(new DOMSource(doc), new StreamResult(aFile));
					break;
				} else{
					JOptionPane.showMessageDialog(null, "A conflict happened");
				}
			}
			
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * for(int i = 0; i < manuList.getLength(); i++) { Node paper =
	 * manuList.item(i); if(((Element)paper).getAttribute(NAME).equals(a_title))
	 * { paper = manuList.item(i); // update rec attribute NamedNodeMap attr =
	 * paper.getAttributes(); Node nodeAttr = attr.getNamedItem(RECOMMENDATION);
	 * nodeAttr.setTextContent(String.valueOf(a_recVal)); break; } }
	 * 
	 * @param a_title
	 * @param a_recVal
	 */
	public void submitRecommendation(final String a_title, final int a_recVal) {
		NodeList manuList = doc.getElementsByTagName(MANUSCRIPT);
		for (int i = 0; i < manuList.getLength(); i++) {
			Element paper = (Element) manuList.item(i);
			if ((paper).getAttribute(NAME).equals(a_title)) {
				paper.getAttributeNode(RECOMMENDATION).setNodeValue(
						String.valueOf(a_recVal));
				break;
			}
		}
		// write specific xml tag to XML file
		File aFile = new File("src/xmlfiles/conferences.xml");
		// save the result
		Transformer xformer;
		try {
			xformer = TransformerFactory.newInstance().newTransformer();
			xformer.transform(new DOMSource(doc), new StreamResult(aFile));
		} catch (TransformerConfigurationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (TransformerFactoryConfigurationError e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (TransformerException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	public void makeApproval(final String a_title, final int a_aprVal) {
		NodeList manuList = doc.getElementsByTagName(MANUSCRIPT);
		for (int i = 0; i < manuList.getLength(); i++) {
			Element paper = (Element) manuList.item(i);
			if ((paper).getAttribute(NAME).equals(a_title)) {
				paper.getAttributeNode(APPROVAL).setNodeValue(
						String.valueOf(a_aprVal));
				break;
			}
		}
		// write specific xml tag to XML file
		File aFile = new File("src/xmlfiles/conferences.xml");
		// save the result
		Transformer xformer;
		try {
			xformer = TransformerFactory.newInstance().newTransformer();
			xformer.transform(new DOMSource(doc), new StreamResult(aFile));
		} catch (TransformerConfigurationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (TransformerFactoryConfigurationError e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (TransformerException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}


	/**
	 * Returns the the name of a person, given their role, and the manuscript
	 * they are in use for author, subpc, and pc, Won't work for reviewer
	 * because there can be more than one reviewer.
	 * 
	 * @param parent
	 *            A manuscript element
	 * @param role
	 *            the role of the person
	 * @return The name of the person at the given role
	 */
	private String getName(final Element parent, final String role) {
		NodeList list = parent.getElementsByTagName(role);
		Element person = null;
		if (list.getLength() > 0) { // if the NodeList is empty, just return an
									// empty string
			person = (Element) list.item(0);
		} else {
			return "";
		}

		return person.getAttribute(NAME);
	}

	public ArrayList<String> getListOfConferences() {
		ArrayList<String> conferenceList = new ArrayList<String>();

		NodeList nList = doc.getElementsByTagName(CONFERENCE); // generate a
																// node list of
																// conferences

		for (int i = 0; i < nList.getLength(); i++) { // generate a Review
														// object for each
														// review/reviewer
			Element confEle = (Element) nList.item(i);
			Conference confObj = new Conference(confEle.getAttribute(NAME),
					confEle.getAttribute(DATE), confEle.getAttribute(VENUE),
					confEle.getAttribute(DEADLINE));
			conferenceList.add(confObj.getName()); // add to ArrayList
		}
		return conferenceList;
	}

	/**
	 * Creates a conference object with the fields set.
	 * 
	 * @param confEle
	 *            The element that should be a conference
	 * @return the defined conference if confEle is a valid conference element
	 *         returns null otherwise.
	 */
	private Conference generateConference(Element confEle) {
		Conference conf = null;
		if (confEle != null && confEle.getNodeName().equals(CONFERENCE)) {
			String name = confEle.getAttribute(NAME);
			String date = confEle.getAttribute(DATE);
			String venue = confEle.getAttribute(VENUE);
			String deadline = confEle.getAttribute(DEADLINE);
			conf = new Conference(name, date, venue, deadline);
		}
		return conf;
	}

	/**
	 * Finds the first instance of a desired element in a NodeList
	 * 
	 * @param list
	 *            A NodeList to search
	 * @param name
	 *            The name to search for
	 * @return the first instance of the element if it was found, null otherwise
	 */
	private Element getElementFromList(final NodeList list, final String name) {
		Element cEle = null; // the element that will contain the conference.
		for (int i = 0; i < list.getLength(); i++) {
			cEle = (Element) list.item(i); // get the node, and cast it to an
											// Element for inspection.

			if (cEle.getAttribute("name").equals(name)) { // check if this is
															// the correct
															// element.
				break;
			}
			cEle = null; // reset cEle, so an unwanted element is not returned
							// if there are no
							// instances of the correct element.
		}
		return cEle;
	}
	
	public void createConf(final Conference a_conf, final String a_pc){
		InputStream stream = FileParser.class.getResourceAsStream("/xmlfiles/conferences.xml");
		try {
			DocumentBuilderFactory dbFactory = DocumentBuilderFactory
					.newInstance();
			DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
			doc = dBuilder.parse(stream); // create dom
			stream.close(); // stream no longer needed, so close it.
			doc.getDocumentElement().normalize();
			NodeList hqList = doc.getElementsByTagName("Headquarters");
			for(int i = 0; i < hqList.getLength(); i++) {
				Element hqEle = (Element)hqList.item(i);
				if(a_conf != null){
					Element conf = doc.createElement("Conference");
					Attr dateAttr = doc.createAttribute("date");
					dateAttr.setNodeValue(a_conf.getDate());
					conf.setAttributeNode(dateAttr);
					
					Attr deadlineAttr = doc.createAttribute("deadline");
					deadlineAttr.setNodeValue(a_conf.getDeadline());
					conf.setAttributeNode(deadlineAttr);
					
					Attr nameAttr = doc.createAttribute("name");
					nameAttr.setNodeValue(a_conf.getName());
					conf.setAttributeNode(nameAttr);
					
					Attr venueAttr = doc.createAttribute("venue");
					venueAttr.setNodeValue(a_conf.getVenue());
					conf.setAttributeNode(venueAttr);
					
					Element pc = doc.createElement("PC");
					Attr pcAttr = doc.createAttribute("name");
					pcAttr.setNodeValue(a_pc);
					pc.setAttributeNode(pcAttr);
					
					conf.appendChild(pc);
					hqEle.appendChild(conf);
					System.out.println("It went here");
			
				}
			}
								
			File aFile = new File("src/xmlfiles/conferences.xml");
			// save the result
			TransformerFactory transformerFactory = TransformerFactory.newInstance();
			Transformer transformer = transformerFactory.newTransformer();
			transformer.setOutputProperty(OutputKeys.INDENT, "yes");
			transformer.setOutputProperty(
					"{http://xml.apache.org/xslt}indent-amount", "3");
			DOMSource source = new DOMSource(doc);
			StreamResult result = new StreamResult(aFile);
			transformer.transform(source, result);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	
	public Conference getConference(String conferenceName) {
		Conference conf = null;
		NodeList nList = doc.getElementsByTagName(CONFERENCE);
		for (int i = 0; i < nList.getLength(); i++) {
			Element confEle = (Element) nList.item(i);
			if(confEle.getAttribute(NAME).equalsIgnoreCase(conferenceName)){
				conf = generateConference(confEle);
				break;
			}
		}
		return conf;
	}

	/**
	 * writes all fields of passed manuscript to xml. deletes all reviews and
	 * rewrites from reviews list to handle adding, deleteing and changing
	 * reviews.
	 * @author Samba,Patrick
	 * @author Dustin Striplin
	 * @param the
	 *            title before changes.
	 * @param a_manuscript
	 *            manuscript with changes.
	 */
	public void saveManuscript(String a_title, Manuscript a_manuscript) {
		
		// get the name of the author and the conference
		String conference = a_manuscript.getConference().getName();
		String author = a_manuscript.getAuthor();

		// create a list of available conferences
		NodeList nList = doc.getElementsByTagName(CONFERENCE);
		// find the correct conference.

		
		Element cEle = getElementFromList(nList, conference);
		if (cEle != null) {

			nList = cEle.getElementsByTagName(MANUSCRIPT);
				Element parent;

			for (int i = 0; i < nList.getLength(); i++) {
				Element mEle = (Element) nList.item(i);
				parent = (Element) mEle.getParentNode();
				String check = getName(mEle, Roles.AUTHOR.toString());
				
				if (mEle.getNodeName().equals(MANUSCRIPT)
						&& check.equals(a_manuscript.getAuthor())
						&& mEle.getAttribute(NAME).equals(
								a_title)) {

					Node node = mEle.getAttributeNode(LINK);
					node.setNodeValue(a_manuscript.getLink());

					node = mEle.getAttributeNode(NAME);
					node.setNodeValue(a_manuscript.getTitle());

					node = mEle.getAttributeNode(RECOMMENDATION);
					node.setNodeValue(String.valueOf(a_manuscript
							.getRecommendation()));

					node = mEle.getAttributeNode(APPROVAL);
					node.setNodeValue(String.valueOf(a_manuscript
							.getApproval()));
					
					

					// change SubPC
					NodeList tempList = parent
							.getElementsByTagName(Roles.SUBPC
									.toString());
					Element person = null;
					person = (Element) tempList.item(0);
					node = person.getAttributeNode(NAME);
					node.setNodeValue(a_manuscript.getSubpc());
					
					// change pc
					tempList = parent
							.getElementsByTagName(Roles.PC
									.toString());
					person = null;
					person = (Element) tempList.item(0);
					node = person.getAttributeNode(NAME);
					node.setNodeValue(a_manuscript.getPc());

					filterElements(mEle, "Reviewer");

					for (int k = 0; k < a_manuscript.getReviews()
							.size(); k++) {
						Review aReview = a_manuscript.getReviews().get(
								k);
						Element review = doc.createElement("Reviewer");
						mEle.appendChild(review);

						Attr reviewNameAttr = doc
								.createAttribute("name");
						reviewNameAttr.setValue(aReview.getReviewer());
						review.setAttributeNode(reviewNameAttr);

						Attr reviewLinkAttr = doc
								.createAttribute("link");
						reviewLinkAttr
								.setValue(aReview.getReviewLink());
						review.setAttributeNode(reviewLinkAttr);

					}
				}
			}

			// write specific xml tag to XML file
			File aFile = new File("src/xmlfiles/conferences.xml");
			// save the result
			Transformer xformer;
			try {
				xformer = TransformerFactory.newInstance()
						.newTransformer();
				xformer.setOutputProperty(OutputKeys.INDENT, "yes");
				xformer.setOutputProperty(
						"{http://xml.apache.org/xslt}indent-amount",
						"3");
				xformer.transform(new DOMSource(doc), new StreamResult(
						aFile));
			} catch (TransformerConfigurationException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (TransformerFactoryConfigurationError e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (TransformerException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
	
	public void signUp(final String a_name, final String a_email, final String a_phone) {
		InputStream stream = FileParser.class.getResourceAsStream("/xmlfiles/conferences.xml");
		try {
			DocumentBuilderFactory dbFactory = DocumentBuilderFactory
					.newInstance();
			DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
			doc = dBuilder.parse(stream); // create dom
			stream.close(); // stream no longer needed, so close it.
			doc.getDocumentElement().normalize();
			Element users = (Element) doc.getElementsByTagName("Users").item(0);
			Element user = doc.createElement("User");
			Attr nameAttr = doc.createAttribute("name");
			nameAttr.setValue(a_name);
			user.setAttributeNode(nameAttr);
			
			Attr emailAttr = doc.createAttribute("email");
			emailAttr.setValue(a_email);
			user.setAttributeNode(emailAttr);
			
			Attr phoneAttr = doc.createAttribute("phone");
			phoneAttr.setValue(a_phone);
			user.setAttributeNode(phoneAttr);
			users.appendChild(user);
			File aFile = new File("src/xmlfiles/conferences.xml");
			// save the result
			TransformerFactory transformerFactory = TransformerFactory.newInstance();
			Transformer transformer = transformerFactory.newTransformer();
			transformer.setOutputProperty(OutputKeys.INDENT, "yes");
			transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "3");
			transformer.transform(new DOMSource(doc), new StreamResult(aFile));
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * removes all of passed parent's child nodes of name "filter"
	 * 
	 * @param parent
	 *            parent of the child nodes to be deleted
	 * @param filter
	 *            name of tags to be deleted
	 */
	private void filterElements(Node parent, String filter) {
		NodeList children = parent.getChildNodes();

		for (int i = 0; i < children.getLength(); i++) {
			Node child = children.item(i);

			// only interested in elements
			if (child.getNodeType() == Node.ELEMENT_NODE) {

				// remove elements whose tag name = filter
				// otherwise check its children for filtering with a recursive
				// call
				if (child.getNodeName().equals(filter)) {
					parent.removeChild(child);
				} else {
					filterElements(child, filter);
				}

			}
		}
	}
	
	public TreeSet<String> getUserList(final String a_name) {
		TreeSet<String>	userList = new TreeSet<String>();
		//NodeList nList = doc.getElementsByTagName(CONFERENCE);
		NodeList authorList = doc.getElementsByTagName(Roles.AUTHOR.toString());
		NodeList pcList = doc.getElementsByTagName(Roles.PC.toString());
		NodeList subpcList = doc.getElementsByTagName(Roles.SUBPC.toString());
		NodeList reviewerList = doc.getElementsByTagName(Roles.REVIEWER.toString());
			for (int i = 0; i < authorList.getLength(); i++) { // generate a Review
				Element authorEle = (Element) authorList.item(i);
					userList.add(authorEle.getAttribute(NAME));

			}
			for (int i = 0; i < reviewerList.getLength(); i++) { // generate a Review
				Element reviewerEle = (Element) reviewerList.item(i);
					userList.add(reviewerEle.getAttribute(NAME));

			}
			for (int j = 0; j < pcList.getLength(); j++) { // generate a Review
				Element pcEle = (Element) pcList.item(j);
					userList.add(pcEle.getAttribute(NAME));

			}
			for (int k = 0; k < subpcList.getLength(); k++) { // generate a Review
				Element subpcEle = (Element) subpcList.item(k);
					userList.add(subpcEle.getAttribute(NAME));
			}
	
		return userList;
	}
	
	public ArrayList<String> getUser() {
		ArrayList<String> userList = new ArrayList<String>();

		try {
			InputStream stream = FileParser.class
					.getResourceAsStream("/xmlfiles/Users.xml");

			DocumentBuilderFactory dbFactory = DocumentBuilderFactory
					.newInstance();
			DocumentBuilder dBuilder;
			dBuilder = dbFactory.newDocumentBuilder();

			Document dom = dBuilder.parse(stream); // create dom
			stream.close(); // stream no longer needed, so close it.
			dom.getDocumentElement().normalize();

			Element userNode = dom.getDocumentElement();
			NodeList nList = userNode.getChildNodes();
			for (int i = 0; i < nList.getLength(); i++) { // generate a Review
															// object for each
															// review/reviewer
				Node confEle = nList.item(i + 1);
				System.out.println("it went here " + nList.getLength());
				System.out.println("it went here "
						+ nList.item(i).getNodeName());

			}
		} catch (SAXException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ParserConfigurationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		return userList;
	}

	/**
	 * parses xml file for user and returns applicable attributes
	 * 
	 * @param role
	 *            the role of user being created
	 * @param name
	 *            The name of user being created
	 * @param conference
	 *            Conference the user is attending
	 * @return arraylist of attributes
	 */
	public ArrayList<String> createUser(String role, String name,
			String conference) {
		// create a file parser, and store the xml document as a dom in memory

		ArrayList<String> list = new ArrayList<String>();
		try {
			InputStream stream = FileParser.class
					.getResourceAsStream("/xmlfiles/Users.xml");

			DocumentBuilderFactory dbFactory = DocumentBuilderFactory
					.newInstance();
			DocumentBuilder dBuilder;

			dBuilder = dbFactory.newDocumentBuilder();

			Document dom = dBuilder.parse(stream); // create dom
			stream.close(); // stream no longer needed, so close it.
			dom.getDocumentElement().normalize();

			NodeList nList = dom.getElementsByTagName(role);
			Element cEle = getElementFromList(nList, role);

			list = getUserData(role, name, conference, nList);

		} catch (SAXException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ParserConfigurationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		return list;
	}

	/**
	 * find the attributes in the xml file and return to createUser()
	 * 
	 * @param role
	 *            the role of user being created
	 * @param name
	 *            The name of user being created
	 * @param conference
	 *            Conference the user is attending
	 * @param nList
	 *            list of nodes in the xml file
	 * @return array list of attributes
	 */
	private ArrayList<String> getUserData(String role, String name,
			String conference, NodeList nList) {
		ArrayList<String> list = new ArrayList<String>();
		Element ele; // the current element we are checking

		// loop through node list
		// check if this node is associated with the user

		for (int i = 0; i < nList.getLength(); i++) {
			ele = (Element) nList.item(i);

			if (ele.getNodeName().equals(role)) {

				if (ele.getAttribute(NAME).equals(name)
						&& ele.getAttribute(CONFERENCE).equals(conference)) { // check
																				// if
																				// the
																				// element
																				// is
																				// associated
																				// with
																				// this
																				// user

					String email, phone;

					NodeList alist = ele.getElementsByTagName("Email");
					Element field = (Element) alist.item(0);
					email = field.getAttribute("email");
					alist = ele.getElementsByTagName("Phone");
					field = (Element) alist.item(0);
					phone = field.getAttribute("phone");

					list.add(email);
					list.add(phone);

				}
			}

		}
		return list;
	}

	public boolean authenticateUser(String role, String name, String conference) {
		NodeList nList = doc.getElementsByTagName(CONFERENCE); // generate a
																// node list of
																// conferences
		Element cEle = getElementFromList(nList, conference);
		NodeList aList = cEle.getElementsByTagName(role);
		Element user = getElementFromList(aList, name);
		return (user != null);
	}
	
	public boolean authenticateUser(String role, String name) {
		NodeList aList = doc.getElementsByTagName(role);
		Element user = getElementFromList(aList, name);
		return (user != null);
	}
	/**
	 * Author could be able to unsubmit his manuscripts using this method.
	 * @author SAMBA.R
	 * @param node.removeChild(child)
	 *            manuscript tags gets deleted for which the author chooses to unsubmit
	 *            due to which the paper gets deleted from conferences.xml
	 */
	// To delete manuscript based on manuscript name
	public void deleteManuscript(String role, String conference,
			ArrayList<Manuscript> aManuscriptList) {

			Manuscript aManuscriptObj = aManuscriptList.get(0);

			// generate a node list of conferences
			NodeList nList = doc.getElementsByTagName(CONFERENCE);
			// find the correct conference.
			Element cEle = getElementFromList(nList, conference);
			Element ele;
			// get a list of each instance of this role from the conference
			if (cEle != null) {
				ArrayList<Manuscript> manuscriptList = readManuscriptDataFromXML(
						cEle, cEle.getElementsByTagName(role), conference);
				if (manuscriptList.size() > 0) {
					if (nList.getLength() > 0) {
						for (int index = 0; index < nList.getLength(); index++) {
						ele = (Element) nList.item(index);
						if(ele.getAttribute(NAME).equals(conference)){
							NodeList n = ele.getElementsByTagName("PC");
							Node node = (Node) n.item(0);	
							NodeList childList = node.getChildNodes();
						int count = 0;
						for (int x = 0; x < childList.getLength(); x++) {
							Node child = (Node) childList.item(x);
							if ((child.getNodeType() == Node.ELEMENT_NODE)
									&& (child.getNodeName()
											.equalsIgnoreCase("MANUSCRIPT"))) {
								Manuscript manuscript = (Manuscript) manuscriptList
										.get(count);
								count++;
								// delete manuscript tag based on manuscript
									// name
									if (aManuscriptObj != null
											&& manuscript != null
											&& conference != null
											&& manuscript.getConference() != null
											&& manuscript.getConference().getName() != null
											&& manuscript.getConference().getName()
													.trim()
													.equals(conference.trim())
											&& aManuscriptObj.getTitle() != null
											&& manuscript.getTitle() != null
											&& aManuscriptObj
													.getTitle()
													.trim()
													.equals(manuscript.getTitle()
															.trim())) {
										node.removeChild(child);
									}
							}
						}
						}
					}
					}

					// write specific xml tag to XML file
					File aFile = new File("src/xmlfiles/conferences.xml");
					// save the result
					Transformer xformer;
					try {
						xformer = TransformerFactory.newInstance().newTransformer();
						xformer.transform(new DOMSource(doc), new StreamResult(
								aFile));
					} catch (TransformerConfigurationException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					} catch (TransformerFactoryConfigurationError e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					} catch (TransformerException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
			}

		}
	/**
	 * 
	 * @author SAMBA
	 */

	private ArrayList<Manuscript> readManuscriptDataFromXML(
			final Element confEle, final NodeList nList, final String conference) {
		ArrayList<Manuscript> mList = new ArrayList<Manuscript>();
		Element ele; // the current element we are checking
		Element parent; // the parent of ele, this can be either Conference, or
						// Manuscript.
		Conference conf = generateConference(confEle); // create a conference
														// object to store in
														// all
		// manuscripts that are created in this method
		// since all manuscripts are from the same conference.
		if (conf == null)
			return null; // TODO should send an error, but... I might do that
							// later
		// loop through node list
		// check if this node is associated with the user
		// if it is then create a manuscript
		// set all of the fields
		// then add the manuscript to the ArrayList.
		for (int i = 0; i < nList.getLength(); i++) {
			ele = (Element) nList.item(i);
			parent = (Element) ele.getParentNode(); // look at parent node,
			if (parent.getNodeName().equals(MANUSCRIPT)) { // check if the
															// Element is a
															// descendant of
															// Manuscript

				String author, title, pc, subpc, paperLink; // create variables
															// for input to the
															// manuscript
				int recommendation, approval;
				ArrayList<Review> reviews = null;

				title = parent.getAttribute(NAME); // get attributes from
													// Manuscript tag
				paperLink = parent.getAttribute(LINK);
				recommendation = Integer.parseInt(parent
						.getAttribute(RECOMMENDATION));
				approval = Integer.parseInt(parent.getAttribute(APPROVAL));

				pc = getName(parent, Roles.PC.toString()); // get pc name
				subpc = getName(parent, Roles.SUBPC.toString()); // get subpc
																	// name
				author = getName(parent, Roles.AUTHOR.toString()); // get author
																	// name

				reviews = getReviews(parent); // get a list of review objects
												// containing
				// the reviewer name, and a link to the review.

				mList.add(new Manuscript(author, title, paperLink, pc, subpc,
						recommendation, approval, conf, reviews));
			}
		}
		return mList;
	}
	/**
	 * Author could be able to submit his manuscrips using this method.
	 * @author Samba
	 * @param createElement("Manuscript")
	 *            new manuscript tags gets created and inserts a new 
	 *            Manuscript with title and link
	 */
	public void insertManuscript(String conference,
			ArrayList<Manuscript> manuscriptList) {

		
		try {
			
			NodeList nList;
			if (manuscriptList.size() > 0) {
				
				nList = doc.getElementsByTagName(CONFERENCE);
				for (int i = 0; i < manuscriptList.size(); i++) {
					Manuscript manuscript = (Manuscript) manuscriptList.get(i);
					// to display manuscript tag.
					Element cEle = getElementFromList(nList, conference);
					NodeList n = cEle.getElementsByTagName("PC");
					Element mEle = (Element) n.item(0);
					Element rootElement = doc.createElement("Manuscript");
					mEle.appendChild(rootElement);

					// to display manuscript name
					Attr attr1 = doc.createAttribute("name");
					attr1.setValue(manuscript.getTitle());
					rootElement.setAttributeNode(attr1);
					

					// display manuscript link if manuscript.getLink not null
					if (manuscript != null && manuscript.getLink() != null) {
						Attr attr2 = doc.createAttribute("link");
						attr2.setValue(manuscript.getLink());
						rootElement.setAttributeNode(attr2);
					}

					// display manuscript rec
						Attr attr3 = doc.createAttribute("rec");
						attr3.setValue(String.valueOf("0"));
						rootElement.setAttributeNode(attr3);
					

					// to display approval status
						Attr attr4 = doc.createAttribute("approval");
						attr4.setValue(String.valueOf("0"));
						rootElement.setAttributeNode(attr4);
					

					// to display Author if manuscript.getAuthor() not null
					if (manuscript != null && manuscript.getAuthor() != null) {
						Element author = doc.createElement("Author");
						rootElement.appendChild(author);

						Attr authorAttr = doc.createAttribute("name");
						authorAttr.setValue(manuscript.getAuthor());
						author.setAttributeNode(authorAttr);
					}

					// to display SUBPC
					Element subProgram = doc.createElement("SubPC");
					rootElement.appendChild(subProgram);

					Attr SubAttr = doc.createAttribute("name");
					SubAttr.setValue("Sub Program Chair not assigned");
					subProgram.setAttributeNode(SubAttr);

					// to display program chair
					Element programChair = doc.createElement("PC");
					rootElement.appendChild(programChair);

					Attr pcAttr = doc.createAttribute("name");
					pcAttr.setValue("Program Chair not assigned");
					programChair.setAttributeNode(pcAttr);

					Review aReview = new Review("null", "null");

					Element review = doc.createElement("Reviewer");
					rootElement.appendChild(review);
					if (aReview != null && aReview.getReviewer() != null) {

						Attr reviewNameAttr = doc.createAttribute("name");
						reviewNameAttr.setValue(aReview.getReviewer());
						review.setAttributeNode(reviewNameAttr);
					}
					if (aReview != null && aReview.getReviewLink() != null) {

						Attr reviewLinkAttr = doc.createAttribute("link");
						reviewLinkAttr.setValue(aReview.getReviewLink());
						review.setAttributeNode(reviewLinkAttr);
					}

				}

				File aFile = new File("src/xmlfiles/conferences.xml");
				// save the result
				Transformer xformer = TransformerFactory.newInstance()
						.newTransformer();
				xformer.setOutputProperty(OutputKeys.INDENT, "yes");
				xformer.setOutputProperty(
						"{http://xml.apache.org/xslt}indent-amount", "3");
				xformer.transform(new DOMSource(doc), new StreamResult(aFile));
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

	}
}